﻿using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using MyServer.Common.Tools;
using System.ComponentModel;
using FrameWork.Log;
using FrameWork.Setting;

namespace MyServer.Common
{

    /*数据发送基类说明
     * 工作方式：
     * 1.启动发送工作流(SendMainTask)
     *   发送工作流执行->检测发送队列是否为空是则监听并重复此步，否则开始发送队列中最先到达的数据。
     * 2.执行时会取出发送队列中最先到达的数据并异步操作
     * 3.读取完毕后会同步执行OnSendCompelete事件
     * 4.发送数据之前会同步调用OnBeforeSend，当且仅当该方法返回值为真时继续发送，否则跳过发送当前数据
     */

    /// <summary>
    /// 表示数据发送器基类
    /// </summary>
    public abstract class DataSenderBase : QueueOperateItemBase
    {
        #region========私有变量========
        private object LockObj = new object();
        #endregion

        #region========公有属性========

        /// <summary>
        /// 获取与发送器绑定的数据中心
        /// </summary>
        public DataCenterBase DataCenter { get; private set; }
        /// <summary>
        /// 获取数据发送器使用的压缩器
        /// </summary>
        public DataCompressorBase Compressor { get; private set; }
        #endregion

        #region========私有函数========

        /// <summary>
        /// 发送一个数据包集合
        /// </summary>
        /// <param name="data">要发送的数据包集合</param>
        /// <returns>一个值，表示是否正确发送数据包</returns>
        /// <remarks>在本函数操作需同步执行（入data数据一次操作不能完成可分步操作）</remarks>
        protected virtual OperateResult Send(ref DataPackageCollection data)
        {
            lock (LockObj)
            {
                try
                {
                    MemoryStream stream = new MemoryStream();
                    BinaryWriter bw = new BinaryWriter(stream);
                    if (data.State == PackageCollectionState.Created)
                    {
                        bw.Write(true);
                        byte[] sendbuffer = data.ToByte();
                        if(Compressor!=null)
                        {
                            sendbuffer = Compressor.Compress(sendbuffer);
                        }
                        bw.Write(sendbuffer.Length);
                        bw.Write(sendbuffer);
                        bw.Flush();
                        if (data.DataCount == 0)
                        {
                            data.State = PackageCollectionState.ReadyForSend;
                            data.OperatedPkgCount = 0;
                        }
                        else
                        {
                            data.State = PackageCollectionState.SendCompelete;
                        }
                    }
                    else
                    {
                        DataPackage pkg = data[data.OperatedPkgCount];
                        bw.Write(false);
                        byte[] sendbuffer = pkg.ToByte();
                        if (Compressor != null)
                        {
                            sendbuffer = Compressor.Compress(sendbuffer);
                        }
                        bw.Write(sendbuffer.Length);
                        bw.Write(sendbuffer);
                        bw.Flush();
                        data.OperatedPkgCount++;
                    }
                    SendData(data.Tag, stream.ToArray());
                    return OperateResult.Success;
                }
                catch
                {
#if DEBUG
                    throw;
#else
                    return OperateResult.Fail;
#endif
                }
            }
        }

        #endregion

        #region========抽象函数========

        /// <summary>
        /// 向基础连接发送数据
        /// </summary>
        /// <param name="Tag">存储基础连接信息的对象</param>
        /// <returns></returns>
        protected abstract void SendData(object Tag, byte[] Data);

        #endregion

        #region========构造函数========
        public DataSenderBase(DataCenterBase Center,DataCompressorBase Compressor=null)
        {
            this.DataCenter = Center;
            this.Compressor = Compressor;
        }

        #endregion

        #region========继承函数========

        protected override OperateResult DoOperateSetp(DataPackageCollection pkg, out DataPackageCollection repkg)
        {
            repkg = null;
            return Send(ref pkg);
        }

        protected override bool BeforeOperateSetp(DataPackageCollection pkg)
        {
            return true;
        }

        protected override bool AfterOperateSetp(DataPackageCollection pkg)
        {
            if (pkg.OperatedPkgCount < pkg.Count || pkg.State == PackageCollectionState.ReadyForSend)//判定数据包列表是否发送完毕
            {
                pkg.State = PackageCollectionState.Sending;
                return true;
            }
            else if (pkg.OperatedPkgCount == pkg.Count)//数据包已发送完毕
            {
                pkg.State = PackageCollectionState.SendCompelete;
            }
            else//数据包发送数据出错
            {
                pkg.State = PackageCollectionState.ErrorSend;
                PrintLog(LogType.Error, "数据包发送出错！", pkg);
            }
            return false;
        }

        #endregion

    }
}
